﻿/// <reference path="../../../../SIR.Web/scripts/_references.js" />
/// <reference path="../../../../SIR.Web/scripts/jquery-1.9.1.js" />
/// <reference path="../../../../SIR.Web/scripts/angular.js" />
/// <reference path="../../../../SIR.Web/scripts/angular-mocks.js" />

/// <reference path="../../../../SIR.Web/app/app.js" />
/// <reference path="../../../../SIR.Web/app/common/common.js" />
/// <reference path="../../../../SIR.Web.Tests/JavaScript/sir-mock.js" />
/// <reference path="../../../../SIR.Web/app/authenticate/authenticate.js" />
/// <reference path="../../../../SIR.Web/app/authenticate/services/auth-service.js" />
/// <reference path="../../../../SIR.Web/app/authenticate/controllers/user-control-panel-controller.js" />

describe('User Control Panel Controller - Log In:', function () { 
	'use strict';
	// declare the variables and the modules
	var scope, location, controller, rootScope, $httpBackend, notifyService;

	beforeEach(module('ui.router'));
	beforeEach(module('app.common'));
	beforeEach(module('app.authenticate'));

	beforeEach(inject(function ($injector, $controller, $rootScope, authService, notify) {
		// intialize the variables for each test
		$httpBackend = $injector.get('$httpBackend');
		rootScope = $rootScope;
		scope = $rootScope.$new();
		notifyService = notify;
		// expect the login request
		$httpBackend.expectPOST('/api/Authentication/LogIn').respond({ Successful: false, Content: null, Message: '' });
		controller = $controller('ControlPanelController', { $scope: scope, $state: {}, authService: authService });
		$httpBackend.flush();
		// spy on the response handler and the notify service
		spyOn(controller, 'handleLogInReply').andCallThrough();
		spyOn(notifyService, 'warning').andCallThrough();
		spyOn(notifyService, 'error').andCallThrough();
	}));
	// expect that all of the request have been handled
	afterEach(function () {
		$httpBackend.verifyNoOutstandingExpectation();
		$httpBackend.verifyNoOutstandingRequest();
	});

	describe('Controller - User Login : (Total: 5)', function () {
		it('[1] Produce \'Email is required\' message when user attempts to log in with an no email', function () {
			// empty email, populated password
			scope.model.email = '';
			scope.model.password = 'password';
			// attempt log in
			scope.logIn();
			// expect the email is required message was displayed
			expect(notifyService.warning).toHaveBeenCalledWith('Email is required');
			// expect user to be null and the password to be cleared
			expect(scope.user).toBe(null);
			expect(scope.model.email).toBe('');
			expect(scope.model.password).toBe('');
		});

		it('[2] Produce \'Password is required\' message when user attempts to log in with an email but no password', function () {
			// email populated but password empty
			scope.model.email = 'email';
			scope.model.password = '';
			// attempt log in
			scope.logIn();
			// expect the password required message was shown
			expect(notifyService.warning).toHaveBeenCalledWith('Password is required');
			// expect the user to be null and the password was cleared
			expect(scope.user).toBe(null);
			expect(scope.model.email).toBe('email');
			expect(scope.model.password).toBe('');
		});

		it('[3] Produce \'Invalid email and invalid password\' message when user attempts to log in with an invalid email and invalid password', function () {
			// expect the log in request and response with fail
			$httpBackend.expectPOST('/api/Authentication/LogIn').respond({ Successful: false, Content: null, Message: 'Invalid email and invalid password' });
			// populate the email and password
			scope.model.email = 'email';
			scope.model.password = 'password';
			// attempt log in
			scope.logIn();
			scope.$digest();
			$httpBackend.flush();
			// expect that the error was shown to the user
			expect(notifyService.error).toHaveBeenCalledWith('Invalid email and invalid password');
			// expect the user value is still null and the password was cleared
			expect(scope.user).toBe(null);
			expect(scope.model.email).toBe('email');
			expect(scope.model.password).toBe('');
		});

		it('[4] Produce \'Invalid password\' message when user attempts to login with a valid email and an invalid password three times', function () {
			// expect the log in request and return the fail response
			$httpBackend.expectPOST('/api/Authentication/LogIn').respond({ Successful: false, Content: null, Message: 'Invalid email and invalid password' });
			// populate the email and password
			scope.model.email = 'email';
			scope.model.password = 'password';
			// attempt log in
			scope.logIn();
			scope.$digest();
			$httpBackend.flush();
			// expect that the error was shown to the user
			expect(notifyService.error).toHaveBeenCalledWith('Invalid email and invalid password');
			// expect the user value is still null and the password was cleared
			expect(scope.user).toBe(null);
			expect(scope.model.email).toBe('email');
			expect(scope.model.password).toBe('');
		});

		it('[5] Produce \'Login Successful\' message when user logins with a valid email and a valid password', function () {
			// spy on the logged in state switch
			spyOn(controller, 'showLoggedInState');
			// return a successful response for the log in request
			$httpBackend.expectPOST('/api/Authentication/LogIn').respond({ Successful: true, Content: {}, Message: 'Authentication Successful' });
			// populate the email and password
			scope.model.email = 'email';
			scope.model.password = 'password';
			// attempt log in
			scope.logIn();
			scope.$digest();
			$httpBackend.flush();
			// expect the handler was called
			expect(controller.handleLogInReply).toHaveBeenCalled();
			// expect the that the logged in state is called
			expect(controller.showLoggedInState).toHaveBeenCalled();
			// expect that no warning was displayed
			expect(notifyService.warning).not.toHaveBeenCalled();
			// expect the user was populated and that the email and password were cleared
			expect(scope.user).toNotBe(null);
			expect(scope.user).toNotBe(undefined);
			expect(scope.model.email).toBe('');
			expect(scope.model.password).toBe('');
		});
	});
});